#include "PRBSAutoTask.h"
#include <cstddef>

#include "Logger/LogMacro.h"
#include "Motion/MotionSharedData/MotionSharedData.h"
#include "Utils/UnitConverter/UnitConverter.h"

EDM_STATIC_LOGGER_NAME(s_logger, "motion");

namespace edm {
namespace move {

static auto s_motion_shared = MotionSharedData::instance();

PRBSAutoTask::PRBSAutoTask(size_t axis_idx,
                           std::shared_ptr<std::vector<int16_t>> prbs_data_ptr)
    : AutoTask(AutoTaskType::PRBS), axis_idx_(axis_idx),
      prbs_data_ptr_(prbs_data_ptr), curr_idx_(0), state_(State::Running) {
    if (prbs_data_ptr_ == nullptr) {
        s_logger->warn("PRBSAutoTask constructed with null data pointer");
        state_ = State::Stopping;
        return;
    }

    if (prbs_data_ptr_->empty()) {
        s_logger->warn("PRBSAutoTask constructed with empty data");
        state_ = State::Stopping;
        return;
    }

    if (axis_idx_ >= EDM_AXIS_NUM) {
        s_logger->error("PRBSAutoTask constructed with invalid axis index: {}",
                        axis_idx_);
        state_ = State::Stopping;
        return;
    }

    // 记录起始位置
    start_cmd_axis_ = s_motion_shared->get_global_cmd_axis();
    s_logger->debug("PRBSAutoTask ctor: axis idx: {}, data size: {}, axis start pos: {}", 
        axis_idx_, prbs_data_ptr->size(), start_cmd_axis_.at(axis_idx_));
    
    const auto& options = s_motion_shared->get_options();
    auto it = options.find("ratio_times_1000");
    if (it != options.end()) {
        int ratio_times_1000 = it->second;
        ratio_ = static_cast<double>(ratio_times_1000) / 1000.0;
        s_logger->info("prbs motion: ratio_times_1000: {}, ratio: {}", ratio_times_1000, ratio_);
    }
}

bool PRBSAutoTask::pause() {
    switch (state_) {
    default:
    case State::Stopping:
    case State::Stopped:
        return false;
    case State::Paused:
        return true;
    case State::Running:
        state_ = State::Paused;
        return true;
    }
}

bool PRBSAutoTask::resume() {
    switch (state_) {
    default:
    case State::Stopping:
    case State::Stopped:
        return false;
    case State::Running:
        return false;
    case State::Paused:
        state_ = State::Running; // 可以直接设置为Stopped
        return true;
    }
}

bool PRBSAutoTask::stop(bool immediate [[maybe_unused]]) {
    state_ = State::Stopped;
    return true;
}

double PRBSAutoTask::get_progress_percent() const {
    if (prbs_data_ptr_ == nullptr || prbs_data_ptr_->empty()) {
        return 100.0;
    }

    return (static_cast<double>(curr_idx_) /
            static_cast<double>(prbs_data_ptr_->size())) *
           100.0;
}

void PRBSAutoTask::run_once() {
    switch (state_) {
    default:
    case State::Stopping: {
        state_ = State::Stopped;
        return;
    }
    case State::Stopped:
        return;
    case State::Paused:
        return;
    case State::Running: {
        // 标志一下, 暂用G01标志位
        auto data_record_instance1 =
            s_motion_shared->get_data_record_instance1();
        if (data_record_instance1->is_data_recorder_running()) {
            data_record_instance1->get_record_data_ref()
                .isg01 = 1;
        }

        // 设置当前周期坐标
        auto cmd = start_cmd_axis_;
        cmd[axis_idx_] +=
            static_cast<move::unit_t>((*prbs_data_ptr_)[curr_idx_]) * ratio_; // 注意单位, 这里是blu
        s_motion_shared->set_global_cmd_axis(cmd);

        ++curr_idx_;
        if (curr_idx_ >= prbs_data_ptr_->size()) {
            state_ = State::Stopped;
            s_logger->info("PRBSAutoTask completed all data, curr_idx: {}",
                           curr_idx_);
            return;
        }

        break;
    }
    }
}

} // namespace move
} // namespace edm